﻿/**	@file		file.h
 *	@date		(2007-09-28 20:28:05)/(2011-11-20 13:36:20)
 *-----------------------------------------------------------------------------
 *	@version	1.0.39.67
 *	@author		Nick Shallery	(nicknide@gmail.com)
 *	@copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/

#if			!defined(__LOLIX__LOLI__FILE__H__K_IN_G__)
#define		__LOLIX__LOLI__FILE__H__K_IN_G__
//==============================================================================
//--------------------------------------------------------------------------

#if			!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	"../lolix_macro.h"
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
#if			!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)
	#include	"../lolix_type.h"
#endif	//	!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)
#if			!defined(__LOLIX__TOY__INVOKE_CAST__HPP__K_IN_G__)
	#include	"../toy/invoke_cast.hpp"
#endif	//	!defined(__LOLIX__TOY__INVOKE_CAST__HPP__K_IN_G__)
#if			!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
	#include	"../toy/lx_assert.h"
#endif	//	!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)

namespace lolix{namespace toy{class time_span;}}
namespace lolix{namespace loli{
	namespace _help{
		class	__T_file_sys_base;
	}

class file;
class file_tree;
class file_monitor;	//	监视表
class file_space_trans;
class file_tree_trans_collection;

class file_flow;
class file_stream;
class file_block;
class file_async;
class file_async_result;

//enum FILE_BLOCK_MAPPING_TYPE;
enum FILE_OPEN_FLAG
{
#define	__LOLIX_TMP__DEFINE_FILE_OPEN_FLAG_ITEM(type, value, comment)	type = value ,
#include	"_file_open_flag.inl"
};
}}

class LOLIX_NO_VTABLE lolix::loli::_help::__T_file_sys_base
	: public lolix::itf
{
public:
	struct open_flag;

	typedef	FILE_OPEN_FLAG	FILE_OPEN_FLAG;
	#define	__LOLIX_TMP__DEFINE_FILE_OPEN_FLAG_ITEM(type, value, comment)	static const FILE_OPEN_FLAG type = lolix::loli::type;
	#include	"_file_open_flag.inl"
};


__BEGIN_DISABLE_NO_NAME_STRUCT_WARNING();
struct	lolix::loli::_help::__T_file_sys_base::open_flag
{
	typedef	lx_u32	flag_type;
	LOLIX_INLINE_CALL	open_flag(void){}
	LOLIX_INLINE_CALL	explicit open_flag(flag_type v):flag(v){}

	typedef	FILE_OPEN_FLAG	FILE_OPEN_FLAG;
	#define	__LOLIX_TMP__DEFINE_FILE_OPEN_FLAG_ITEM(type, value, comment)	static const FILE_OPEN_FLAG type = lolix::loli::type;
	#include	"_file_open_flag.inl"

	enum TYPE_MASK
	{	create_new			= 1
	,	create_always		= 2
	,	open_existing		= 3
	,	open_always			= 4
	,	truncate_existing	= 5

	,	_ver				= FILE_OPEN_VER
	};

	LOLIX_INLINE_CALL void mark_stream_read(void)
	{
		flag = 0;
		operat_read = 1;
		type_mask = open_existing;
		with_flow = 1;
		share_read = 1;
	}

	LOLIX_INLINE_CALL void mark_stream_write(void)
	{
		flag = 0;
		operat_write = 1;
		type_mask = create_always;
		with_flow = 1;
	}

	LOLIX_INLINE_CALL void mark_block_read(void)
	{
		flag = 0;
		operat_read = 1;
		type_mask = open_existing;
		with_block = 1;
		share_read = 1;
	}

	LOLIX_INLINE_CALL void mark_block_write(void)
	{
		flag = 0;
		operat_write = 1;
		type_mask = create_always;
		with_block = 1;
		make_path = 1;
	}

	LOLIX_INLINE_CALL void mark_async_read(void)
	{
		flag = 0;
		operat_read = 1;
		type_mask = create_always;
		with_async = 1;
		make_path = 1;
	}

	LOLIX_INLINE_CALL void mark_async_write(void)
	{
		flag = 0;
		operat_write = 1;
		type_mask = create_always;
		with_async = 1;
		make_path = 1;
	}


	union
	{
		flag_type		flag;
		struct
		{
			//	+0x00	bits
			flag_type	share_read		: 1;
			flag_type	share_write		: 1;
			flag_type	share_delete	: 1;
			flag_type	_rsv_00			: 1;
			flag_type	with_flow		: 1;	//	流 : 单向， 不可回退
			flag_type	with_block		: 1;
			flag_type	with_async		: 1;
			flag_type	_rsv_09			: 1;

			//	+0x08	bits
			flag_type	type_mask		: 3;
			flag_type	_rsv_01			: 1;
			flag_type	operat_read		: 1;
			flag_type	operat_write	: 1;
			flag_type	operat_execute	: 1;
			flag_type	_rsv_02			: 1;

			//	+0x10
			flag_type	attr_temp		: 1;
			flag_type	make_path		: 1;
			flag_type	spt_bidir		: 1;	//	双向:修饰流专用， 和 flow 标记组合为 stream
			flag_type	_rsv_03			: 5;

			//	+0x18
			flag_type	_rsv_05			: 3;
			flag_type	optimi_stream	: 1;
			flag_type	optimi_random	: 1;
			flag_type	optimi_mapping	: 1;
			flag_type	_rsv_04			: 2;
		};
		struct
		{
			flag_type	share_flag		: 3;
			flag_type	_rsv_06			: 1;
			flag_type	with_flag		: 3;
			flag_type	_rsv_0a			: 1;

			flag_type	_rsv_07			: 4;
			flag_type	operat_flag		: 3;
			flag_type	_rsv_08			:13;
			flag_type	optimi_flag		: 3;

		};
	};
};
STATIC_ASSERT(sizeof(lolix::loli::_help::__T_file_sys_base::open_flag) == sizeof(lolix::loli::_help::__T_file_sys_base::open_flag::flag_type));
__END_DISABLE_NO_NAME_STRUCT_WARNING();



class LOLIX_NO_VTABLE lolix::loli::file
	: public _help::__T_file_sys_base
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file, lolix::itf, (0x0944aa92, 0x5580432b, 0xa0df64e9, 0x80c19a64));

	LOLIX_INTERFACE(size		, lx_u64		, (void)const);
	LOLIX_INTERFACE(close		, LOLIX_RETNV	, (void));
	LOLIX_INTERFACE(opt_flag	, void			, (open_flag* const out)const);
	LOLIX_INTERFACE(get_name	, LOLIX_RETNV	, (wchar_t full_name[], size_type* const io_file_name_len)const);
	LOLIX_INTERFACE(remove		, LOLIX_RETNV	, (void));
};


class LOLIX_NO_VTABLE lolix::loli::file_tree
	: public _help::__T_file_sys_base
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_tree, lolix::itf, (0x08b3c7d0, 0x88c447de, 0x822ef62d, 0x08e2de20));
	LOLIX_DEFINE_FACTORY((0x298c4af3, 0x31254fb9, 0x976d77b3, 0x6670c1b0), (file_tree** out_ptr));

	enum ENUM_MOUNT_TYPE
	{	MOUNT_TYPE_SPACE	= 1
	,	MOUNT_TYPE_FILE		= 2
	};

	/**
	* \typedef bool (*_T_ENUM_CALL_BACK)(file_tree* root_ft, ENUM_MOUNT_TYPE mount_type, const wchar_t* file_name, size_type name_len, void* usr_dat);
	*
	* \brief	回调对象
	*
	* \param root_ft	:	调用出发点的位置
	* \param mount_type:	回调对象类型
	* \param file_name	:	对象名字
	* \param file_len	:	名字长度
	* \param usr_dat	:	用户自定义数据
	*
	* \return true:继续遍历; false:停止遍历
	**/
	typedef toy::invoker_process<bool, false, toy::type_list<file_tree* /*root_ft*/, ENUM_MOUNT_TYPE /*mount_type*/, const wchar_t* /*file_name*/, size_type /*name_len*/, void* /*usr_dat*/>, void> _T_ENUM_CALL_BACK;

	LOLIX_INTERFACE(collections	, LOLIX_RETNV	, (lolix::loli::file_tree_trans_collection** out_ptr));

	/**
	* \function LOLIX_RETNV mount(file_tree* in_ptr, wchar_t const* file_name, size_type name_len, ENUM_MOUNT_TYPE mount_type);
	* \brief 将一个新的 space 挂载为当前节点的子节点
	*
	* \param	in_ptr		需要挂载的 file_tree
	* \param	file_name	文件路径
	* \param	name_len	文件路径长度
	* \param	mount_type	挂载类型
	*
	* \remark	如果当前挂载点存在同名挂载对象且指定了MOUNT_TYPE_SPACE， 则冲掉已挂载对象
	*			如果当前挂载点存在同名实体对象且指定了MOUNT_TYPE_FILE， 则冲掉实体对象
	**/
	LOLIX_INTERFACE(mount	, LOLIX_RETNV	, (lolix::loli::file_tree* in_ptr, wchar_t const* file_name, size_type name_len, ENUM_MOUNT_TYPE mount_type));

	/**
	* \brief	卸载一个老的挂载点
	*
	* \param	file_name	文件路径
	* \param	name_len	文件路径长度
	* \param	mount_type	挂载类型
	*
	* \return	是否卸载成功
	**/
	LOLIX_INTERFACE(unmount	, LOLIX_RETNV	, (wchar_t const* file_name, size_type name_len, ENUM_MOUNT_TYPE mount_type));

	/**
	* \brief	寻找一个已存在的挂载点
	*
	* \param	out out_ptr	需要挂载的 file_tree
	* \param	file_name	文件路径
	* \param	name_len	文件路径长度
	* \param	trans		转换对象，如果为空， 则使用默认的转换对象
	*
	* \return	是否请求成功
	**/
	LOLIX_INTERFACE(query	, LOLIX_RETNV	, (lolix::loli::file_tree** out_ptr, wchar_t const* file_name, size_type name_len, lolix::loli::file_space_trans* trans));

	/**
	* \brief	打开文件
	*
	* \param	out out_ptr	返回的文件
	* \param	file_name	请求文件的名字
	* \param	name_len	文件名长度
	* \param	opt_flag	操作类型
	*
	* \return	打开是否成功
	**/
	LOLIX_INTERFACE(open	, LOLIX_RETNV	, (file** out_ptr, wchar_t const* file_name, size_type name_len, size_type opt_flag));

	/**
	* \brief	枚举所有子对象
	*
	* \param	call_back	回调对象
	* \param	l4w			是否锁定读写节点, 锁定的话, 能够不使用临时空间
	* \param	usr_dat		用户自定义数据
	*
	* \return	枚举是否成功
	**/
	LOLIX_INTERFACE(enum_dat, LOLIX_RETNV	, (_T_ENUM_CALL_BACK call_back, bool l4w, void* usr_dat));

	#pragma	region	辅助内联函数
	/**
	* \brief	递归查询文件树
	*
	* \param	out	out_ptr	请求到的file_tree
	* \param	file_name	请求的路径
	* \param	name_len	请求的路径的长度
	* \param	trans		文件请求过滤器
	*
	* \return	是否成功
	**/
	LOLIX_RETNV LOLIX_INLINE_CALL query_recursive(file_tree** out_ptr, wchar_t const* file_name, size_type name_len, file_space_trans* trans)
	{
		file_tree* pos = this;
		pos->inc_ref();
		if ( !file_name )
			return LOLIX_ERROR_INVALID_PARAM;

		wchar_t const* file_last = file_name + name_len;
#pragma warning(push)
#pragma	warning(disable : 4127)
		while ( true )
#pragma warning(pop)
		{
			size_type file_len = 0;
			while ( file_name + file_len < file_last && file_name[file_len] && file_name[file_len] != '/' && file_name[file_len] != '\\' )
				++file_len;

			if ( !file_len )
			{
				if ( file_name + file_len >= file_last || !file_name[file_len] )
				{
					*out_ptr = pos;
					return LOLIX_RETNV_OK;
				}
				++file_name;
				continue;
			}

			file_tree* new_pos;
			LOLIX_RETNV rtv = pos->query(&new_pos, file_name, file_len, trans);
			pos->release();
			if ( LOLIX_IS_ERROR(rtv) )
				return rtv;
			pos = new_pos;
			file_name += file_len + 1;
		}
	}


	/**
	* \brief	递归查询文件树
	*
	* \param	out	out_ptr	请求到的文件
	* \param	file_name	请求的路径
	* \param	name_len	请求的路径的长度
	* \param	opt_flag	文件的打开方式
	*
	* \return	是否成功
	**/
	LOLIX_RETNV LOLIX_INLINE_CALL open_recursive(file** out_ptr, wchar_t const* file_name, size_type name_len, size_type opt_flag)
	{
		if ( !file_name )
			return LOLIX_ERROR_INVALID_PARAM;
		if ( !name_len )
			return this->open(out_ptr, file_name, name_len, opt_flag);

		const wchar_t* file_name_start = file_name + name_len - 1;
		while ( file_name_start != file_name )
		{
			if ( *file_name_start == '/' || *file_name_start == '\\' )
				break;
			--file_name_start;
		}

		if ( file_name_start == file_name )
			return this->open(out_ptr, file_name, name_len, opt_flag);

		const size_type path_len = file_name_start - file_name;
		this_type* ptr;
		LOLIX_RETNV rtv;
		if ( LOLIX_IS_ERROR(rtv = this->query_recursive(&ptr, file_name, path_len, 0)) )
			return rtv;
		rtv = ptr->open(out_ptr, file_name_start + 1, name_len - path_len - 1, opt_flag);
		ptr->release();
		return rtv;
	}


	template<typename _Ty, typename _Tproc>
	LOLIX_RETNV LOLIX_INLINE_CALL enum_dat(_Ty* ptr, _Tproc* proc, bool l4w, void* usr_dat)
	{
		return this->enum_dat(_T_ENUM_CALL_BACK(ptr, proc), l4w, usr_dat);
	}
	#pragma endregion
};


class LOLIX_NO_VTABLE lolix::loli::file_monitor
	: public itf
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_monitor, lolix::itf, (0xc938df8c, 0xbc5ae24f, 0x96ad3cef, 0x867468d9));
	LOLIX_DEFINE_FACTORY((0x3af08f09, 0x2db79a43, 0xb07b7a70, 0x318085ab), (file_monitor** out_ptr));

	enum ENUM_CHANGE_TYPE
	{	CHANGE_TYPE_ADD_FILE	= 0x0001
	,	CHANGE_TYPE_DEL_FILE	= 0x0002
	,	CHANGE_TYPE_MODI_FILE	= 0x0004
	,	CHANGE_TYPE_MOUNT_FILE	= 0x0008
	,	CHANGE_TYPE_UMOUNT_FILE	= 0x0010
	,	CHANGE_TYPE_ADD_TREE	= 0x0020
	,	CHANGE_TYPE_DEL_TREE	= 0x0040
	,	CHANGE_TYPE_MOUNT_TREE	= 0x0080
	,	CHANGE_TYPE_UMOUNT_TREE	= 0x0100
	};

	typedef toy::invoker_process<void, false, toy::type_list<file_tree* /*this_ft*/, itf*, ENUM_CHANGE_TYPE, const wchar_t*, size_type, void*>, void> _T_MONITOR_FILE_TREE_CALL_BACK;

	//===========================================================================
	//	设置监视器监视文件对象修改状态
	//---------------------------------------------------------------------------
	//	@call_back	[i ] :	回调对象
	//	@mtype		[i ] :	监视类型
	//	@usrdat		[--] :	用户自定义数据
	//---------------------------------------------------------------------------
	//	枚举是否成功
	//===========================================================================
	LOLIX_INTERFACE(insert	, LOLIX_RETNV	, (_T_MONITOR_FILE_TREE_CALL_BACK call_back, ENUM_CHANGE_TYPE mtype, void* usrdat));

	//===========================================================================
	//	移除监视器监视文件对象修改状态
	//---------------------------------------------------------------------------
	//	@call_back	[i ] :	回调对象
	//	@mtype		[i ] :	监视类型
	//	@usrdat		[--] :	用户自定义数据
	//---------------------------------------------------------------------------
	//	枚举是否成功
	//===========================================================================
	LOLIX_INTERFACE(remove	, LOLIX_RETNV	, (_T_MONITOR_FILE_TREE_CALL_BACK call_back, ENUM_CHANGE_TYPE mtype, void* usrdat));

	//===========================================================================
	//	触发监视器
	//---------------------------------------------------------------------------
	//	@ft			[i ] :	调用的文件父结点
	//	@f			[i ] :	调用的文件对象或者结点对象
	//	@chg_type	[i ] :	操作类型
	//	@name		[i ] :	名字
	//	@name_len	[i ] :	名字长度
	//---------------------------------------------------------------------------
	//		!REMARK:
	//===========================================================================
	LOLIX_INTERFACE(invoke	, LOLIX_RETNV	, (file_tree* ft, itf* f, ENUM_CHANGE_TYPE chg_type, const wchar_t* name, size_type name_len));

	//===========================================================================
	//	得到是否是空的容器
	//---------------------------------------------------------------------------
	//===========================================================================
	LOLIX_INTERFACE(empty	, bool			, (void)const);

	//===========================================================================
	//	size	得到内部回调的个数
	//---------------------------------------------------------------------------
	//===========================================================================
	LOLIX_INTERFACE(size	, size_type		, (void)const);

	template<typename _Ty, typename _Tproc>
	LOLIX_RETNV LOLIX_INLINE_CALL insert(_Ty* ptr, _Tproc proc, ENUM_CHANGE_TYPE mtype, void* usr_dat)
	{
		return this->insert(_T_MONITOR_FILE_TREE_CALL_BACK(ptr, proc), mtype, usr_dat);
	}

	template<typename _Ty, typename _Tproc>
	LOLIX_RETNV LOLIX_INLINE_CALL remove(_Ty* ptr, _Tproc proc, ENUM_CHANGE_TYPE mtype, void* usr_dat)
	{
		return this->remove(_T_MONITOR_FILE_TREE_CALL_BACK(ptr, proc), mtype, usr_dat);
	}
};

class LOLIX_NO_VTABLE lolix::loli::file_space_trans
	: public lolix::itf
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_space_trans, lolix::itf, (0x450671aa, 0x89864896, 0xabd4a03f, 0x3e0b766c));
	LOLIX_DEFINE_FACTORY((0x383e6c93, 0x1dab4be5, 0x8102bc1b, 0x33a47ca0), (file_space_trans** out_ptr));
	LOLIX_INTERFACE(trans	, LOLIX_RETNV	, (file_tree** out_ptr, file_tree* ft, wchar_t const* file_name, size_type name_len));
};


class LOLIX_NO_VTABLE lolix::loli::file_tree_trans_collection
	: public lolix::itf
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_tree_trans_collection, lolix::itf, (0x57d211fe, 0x4c484791, 0x9a7aa4dc, 0xa6afdf27));
	LOLIX_DEFINE_FACTORY((0x30db3eb3, 0x7b114741, 0xbec6abae, 0x678dddc8), (file_tree_trans_collection** out_ptr));
	//===========================================================================
	//	函数说明
	//---------------------------------------------------------------------------
	//	@in_ptr	[i ] :	枚举的 file_trans
	//	@usr_ptr[i ] :
	//---------------------------------------------------------------------------
	//	@: 返回true 表示继续枚举下几个， 否则表示放弃枚举
	//===========================================================================
	typedef toy::invoker_process<bool, false, toy::type_list<file_space_trans* /*in_ptr*/, void* /*usr_ptr*/>, void>	_T_ENUM_INVOKER;
	LOLIX_INTERFACE(insert_trans, LOLIX_RETNV	, (lolix::loli::file_space_trans* in_ptr));
	LOLIX_INTERFACE(remove_trans, LOLIX_RETNV	, (lolix::loli::file_space_trans const* in_ptr));
	LOLIX_INTERFACE(enum_trans	, void			, (_T_ENUM_INVOKER enum_invoke, void* usr_ptr));
};


class LOLIX_NO_VTABLE lolix::loli::file_flow
	: public lolix::loli::file
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_flow, lolix::loli::file, (0x04c4919f, 0x1ebc403f, 0xa2e28e48, 0xb1e04541));

	//===========================================================================
	//	提取输入流的数据
	//---------------------------------------------------------------------------
	//	buf			[ o] : 输出缓冲区
	//	buf_size	[io] : i) 当前缓冲区的大小， o) 实际返回的字节数
	//---------------------------------------------------------------------------
	//	不会更改当前缓冲区的指向， 并且不会影响当前流的内容
	//===========================================================================
	LOLIX_INTERFACE(touch	, LOLIX_RETNV	, (void* buf, size_type* buf_size));

	//===========================================================================
	//	读取输入流的数据
	//---------------------------------------------------------------------------
	//	buf			[ o] : 输出缓冲区
	//	buf_size	[io] : i) 当前缓冲区的大小， o) 实际返回的字节数
	//===========================================================================
	LOLIX_INTERFACE(read	, LOLIX_RETNV	, (void* buf, size_type* buf_size));

	//===========================================================================
	//	写入到输入流
	//---------------------------------------------------------------------------
	//	buf			[ o] : 输入的数据
	//	buf_size	[io] : i) 当前缓冲区的大小， o) 实际写入的字节数
	//===========================================================================
	LOLIX_INTERFACE(write	, LOLIX_RETNV	, (const void* buf	, size_type* buf_size));


	LOLIX_INLINE_CALL LOLIX_RETNV touch(void* buf, size_type buf_size)
		{
			const size_type query_size = buf_size;
			LOLIX_RETNV rtv;
			if ( LOLIX_IS_ERROR(rtv = touch(buf, &buf_size)) )
				return rtv;
			if ( query_size != buf_size )
				return LOLIX_ERROR_LESS_RESOURCE;
			return rtv;
		}

	LOLIX_INLINE_CALL LOLIX_RETNV read(void* buf, size_type buf_size)
		{
			const size_type query_size = buf_size;
			LOLIX_RETNV rtv;
			if ( LOLIX_IS_ERROR(rtv = read(buf, &buf_size)) )
				return rtv;
			if ( query_size != buf_size )
				return LOLIX_ERROR_LESS_RESOURCE;
			return rtv;
		}

	LOLIX_INLINE_CALL LOLIX_RETNV write(const void* buf	, size_type buf_size)
		{
			const size_type old_size = buf_size;
			LOLIX_RETNV rtv;
			if ( LOLIX_IS_ERROR(rtv = write(buf, &buf_size)) )
				return rtv;
			if ( buf_size != old_size )
				return LOLIX_ERROR_LESS_RESOURCE;
			return rtv;
		}
};


class LOLIX_NO_VTABLE lolix::loli::file_stream
	: public lolix::loli::file_flow
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_stream, lolix::loli::file_flow, (0x372323c5, 0xf38a4bdc, 0xa7ad4cf9, 0xd75b839a));
	//	new_offset: [in] need offset, [out] new offset >> distance of begining
	//	int : 0 -> from header, 1 -> from current, 2 -> from end
	LOLIX_INTERFACE(seek	, LOLIX_RETNV	, (lx_i64* new_offset, int));
	LOLIX_INLINE_CALL LOLIX_RETNV seek_to(lx_u64 new_offset)
	{
		lx_i64 cur = new_offset;
		lolix::LOLIX_RETNV rtv;
		if ( LOLIX_CHECK_ERROR(rtv = this->seek(&cur, 0)) )
			return rtv;
		if ( (lx_u64)cur != new_offset )
			return LOLIX_ERROR_INVALID_RANGE;
		return LOLIX_RETNV_OK;
	}
};


class LOLIX_NO_VTABLE lolix::loli::file_block
	: public lolix::loli::file
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_block*, lolix::loli::file, (0x11c8fe7d, 0xc21f4931, 0xb115c5c4, 0x6eea572c));
	enum FILE_BLOCK_MAPPING_TYPE
	{	MAPPING_TYPE_READ	= lolix::loli::file::FILE_OPEN_OPERAT_READ
	,	MAPPING_TYPE_WRITE	= lolix::loli::file::FILE_OPEN_OPERAT_WRITE
	,	MAPPING_TYPE_EXECUTE= lolix::loli::file::FILE_OPEN_OPERAT_EXECUTE
	,	MAPPING_TYPE_VER	= 0
	};
	//enum FILE_BLOCK_MAPPING_TYPE;

	//--------------------------------------------------------------------------
	//	>> 2007-04-12 22:06:26 >>------------------->> 2007-04-12 22:06:26 >>
	//FUNC>>$	:锁定所需要的内存并得到所需求的数据
	//FUNC>>@0	:[out]	返回的内存首地址, 如果请求失败则返回未定义
	//FUNC>>@1	:[in]	操作类型， 读取/写入/插入 等等操作
	//FUNC>>@2	:[in]	从多少个字节开始(如果是写方式, 则只需要 from <= size(), 则表示需要写入 len 长度的数据
	//FUNC>>@3	:[i/o]	in: 需求多少个字节的内存, out: 实际返回了多少个字节
	//FUNC>>#	:
	//			LOLIX_RETNV_OK				没有问题
	//			LOLIX_ERROR_INVALID_PARAM	参数错误
	//			LOLIX_ERROR_OUT_OF_RANGE	"from" 越界
	//--------------------------------------------------------------------------
	LOLIX_INTERFACE(mapping,	LOLIX_RETNV	,	(void** const ptr, size_type mapping_type, lx_u64 from, size_type* const len));

	//--------------------------------------------------------------------------
	//	>> 2007-04-12 22:21:16 >>------------------->> 2007-04-12 22:21:16 >>
	//FUNC>>$	:解除某个范围的锁定
	//FUNC>>@0	:[in]	需要解除的某个起始地址(必须是从 lock 返回的地址, 不能为0)
	//FUNC>>@1	:[in]	需要解除的内存长度, 0 表示全部
	//FUNC>>#	:
	//			LOLIX_RETNV_OK				没有问题
	//			LOLIX_ERROR_INVALID_MEMORY	传入的内存不合法
	//			LOLIX_WARNING_INVALID_STATE	opt_type 状态非法, 但是被纠正了
	//--------------------------------------------------------------------------
	LOLIX_INTERFACE(unmapping,	LOLIX_RETNV,	(void const* const ptr, size_type len/*, bool submit*/));

	class	auto_unmapping;
};


class LOLIX_NO_VTABLE lolix::loli::file_async
	: public lolix::loli::file
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_async, lolix::loli::file, (0x895ad210, 0x17714d0f, 0xb585eb18, 0x9736e6d5));
	typedef file_async_result	async_result;
	typedef lolix::toy::invoker_process<void, false, lolix::toy::type_list<file_async_result*>, void> _T_ASYNC_CALL_BACK;

	//===========================================================================
	//	异步读取文件
	//---------------------------------------------------------------------------
	//	result_dat	[ o] =0	:	读取结果
	//	start_pos	[i ]	:	起始偏移（距离文件头）
	//	opt_size	[i ]	:	读取长度
	//	buf			[i ] =0	:	读取用缓冲区
	//	usr_dat		[i ] =0	:	用户自己使用的数据
	//	call_back	[i ] =0	:	当触发的时候的回调
	//---------------------------------------------------------------------------
	//	REMARK	:	如果 result_dat = 0, 则 call_back 必须有效
	//				当 buf 为 0, 则使用内部缓冲区读取数据
	//===========================================================================
	LOLIX_INTERFACE(read	, LOLIX_RETNV	, (file_async_result** result_dat, lx_u64 start_pos, size_type read_size, void* buf, void* usr_dat, _T_ASYNC_CALL_BACK const* call_back));

	//===========================================================================
	//	异步写入文件
	//---------------------------------------------------------------------------
	//	result_dat	[ o]	:	写入结果
	//	start_pos	[i ]	:	起始偏移（距离文件头）
	//	opt_size	[i ]	:	写入长度
	//	buf			[i ]	:	写入的源数据
	//	usr_dat		[i ] =0	:	用户自己使用的数据
	//	call_back	[i ] =0	:	当触发的时候的回调
	//---------------------------------------------------------------------------
	//	REMARK	:	如果 result_dat = 0, 且 call_back = 0, 则写入后不进行回调通知
	//===========================================================================
	LOLIX_INTERFACE(write	, LOLIX_RETNV	, (file_async_result** result_dat, lx_u64 start_pos, size_type opt_size, const void* buf, void* usr_dat, _T_ASYNC_CALL_BACK const* call_back));

	template<typename _TCnt, typename _Tproc>
	LOLIX_RETNV LOLIX_INLINE_CALL read(file_async_result** result_dat, lx_u64 start_pos, size_type read_size, void* buf, void* usr_dat, _TCnt* cnt_ptr, _Tproc call_back)
	{	const _T_ASYNC_CALL_BACK callback(cnt_ptr, call_back); return this->read(result_dat, start_pos, read_size, buf, usr_dat, &callback);	}

	template<typename _TCnt, typename _Tproc>
	LOLIX_RETNV	LOLIX_INLINE_CALL write(file_async_result** result_dat, lx_u64 start_pos, size_type opt_size, const void* buf, void* usr_dat, _TCnt* cnt_ptr, _Tproc call_back)
	{	const _T_ASYNC_CALL_BACK callback(cnt_ptr, call_back); return this->write(result_dat, start_pos, opt_size, buf, usr_dat, &callback);	}
};


class LOLIX_NO_VTABLE lolix::loli::file_async_result
	: public lolix::itf
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_async_result, lolix::itf, (0x6b2dbc73, 0xdc754cae, 0xbe55176f, 0xbff7d4d6));
	//===========================================================================
	//	得到用户数据
	//===========================================================================
	LOLIX_INTERFACE(usr_dat		, void*			, (void)const);

	//===========================================================================
	//	是否是内部内存
	//---------------------------------------------------------------------------
	//		#内部内存为 read 时， buf 指定为0， 因此内部自动分配的一块内存
	//===========================================================================
	LOLIX_INTERFACE(is_kmem		, bool			, (void)const);

	//===========================================================================
	//	得到结果
	//---------------------------------------------------------------------------
	//	buf		[i ] :	得到当前的缓冲区
	//	dat_size[i ] :	有效数据长度
	//---------------------------------------------------------------------------
	//	LOLIX_ERROR_OUT_OF_SYNC	: 还没有返回
	//===========================================================================
	LOLIX_INTERFACE(get_result	, LOLIX_RETNV	, (void**buf, size_type* dat_size));

	//===========================================================================
	//	取消本次异步访问: 立即在当前上下文触发回调操作， 失败值为 LOLIX_
	//===========================================================================
	LOLIX_INTERFACE(cancel		, LOLIX_RETNV	, (void));

	//===========================================================================
	//	等待结果
	//---------------------------------------------------------------------------
	//	@ts		[i ] :	等待时间多少
	//===========================================================================
	//LOLIX_INTERFACE(wait		, LOLIX_RETNV	, (lolix::toy::time_span* ts));
};


//enum lolix::loli::file_block::FILE_BLOCK_MAPPING_TYPE
//{
//	MAPPING_TYPE_READ	= lolix::loli::file::FILE_OPEN_OPERAT_READ
//,	MAPPING_TYPE_WRITE	= lolix::loli::file::FILE_OPEN_OPERAT_WRITE
//,	MAPPING_TYPE_EXECUTE= lolix::loli::file::FILE_OPEN_OPERAT_EXECUTE
//,	MAPPING_TYPE_VER	= 0
//};


class	lolix::loli::file_block::auto_unmapping
{
	size_type	_size;
	const void*	_ptr;
	file_block*	_fb;
public:
	LOLIX_INLINE_CALL	auto_unmapping(void):_ptr(0){}
	LOLIX_INLINE_CALL	auto_unmapping(file_block* fb, const void* ptr):_fb(fb), _ptr(ptr), _size(0){}
	LOLIX_INLINE_CALL	auto_unmapping(file_block* fb, const void* ptr, size_type mapping_size): _fb(fb), _ptr(ptr), _size(mapping_size){}
	LOLIX_INLINE_CALL	~auto_unmapping(void){__Clear();}
	LOLIX_INLINE_CALL	const void* release(void){ const void* ptr = _ptr; _ptr = 0; return ptr;}
	LOLIX_INLINE_CALL	void reset(void){__Clear();_ptr = 0;}
	LOLIX_INLINE_CALL	void reset(file_block* fb, const void* ptr, size_type size){__Clear(); _fb = fb; _ptr = ptr; _size = size;}
	template<typename _Ty>
	LOLIX_INLINE_CALL	_Ty get(void)const{return (_Ty)_ptr;}
	LOLIX_INLINE_CALL	size_type size(void)const{return _size;}
	LOLIX_INLINE_CALL	void swap(auto_unmapping& o){ lolix::swap(_size, o._size); lolix::swap(_ptr, o._ptr); lolix::swap(_fb, o._fb); }
private:
	LOLIX_INLINE_CALL	void	__Clear(void){if (_ptr) _fb->unmapping(_ptr, _size);}
};


//--------------------------------------------------------------------------
//==============================================================================
#endif	//	!defined(__LOLIX__LOLI__FILE__H__K_IN_G__)
